﻿using CKS.Core.Framework;
using CKS.PLC.Core;
using FreeSql;
using MySqlX.XDevAPI.Relational;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZR.Model.Models.ProductionControl;
using static FreeSql.Internal.GlobalFilter;

namespace CKS.PLC.Action.Subscription {

    /// <summary>
    /// 固化炉结果订阅动作
    /// </summary>
    [SubscribeAction("CuringOvenResultSubscribe")]
    public class CuringOvenResultAction : SubscribeBase {

        public CuringOvenResultAction(DecodeValue decodeValue) : base(decodeValue) {


        }


        /// <summary>
        /// 执行订阅动作的具体实现
        /// </summary>
        public override void ExecuteAction(Dictionary<string, object> execParams) {

            using (var ObjectCo = base.FreeSql.Ado.MasterPool.Get()) {
                var result = DecodeValue.Value.ToBool();
                var conn = ObjectCo.Value;
                var position = DecodeValue.Position;
                //回复绑定关系点位
                var replyRelBindingPos = DecodeValue.GetReplyPosition(position, actionIdFieldFilter: true, actionKeyFieldFilter: true);

                if (result) {

                    var snCodeValue = DecodeValue.GetLinkData(position.ActionId, 0).ToString().TrimEnd();

                    if (string.IsNullOrEmpty(snCodeValue)) {
                        SiemensClient.SetValue(replyRelBindingPos, "0");
                        WriteLogUI($"SN条码为空，保存固化炉进出站记录失败");
                        return;
                    }

                    string msg = string.Empty;

                    int res = 0;

                    var cksWorkRec = new CksWorkRecord();

                    switch (DecodeValue.Position.LocationId) {
                        case 1:
                            msg = "OP90工件入站";
                            cksWorkRec.PlcID = 127;
                            cksWorkRec.ReadDB = 1030; //设置读取DB块
                            cksWorkRec.PrimaryCode = snCodeValue;
                            cksWorkRec.CreatedTime = DateTime.Now;
                            cksWorkRec.MoveInTime = cksWorkRec.ProductionStartTime = DateTime.Now;
                            res = conn.InsertOrUpdate<CksWorkRecord>().SetSource(cksWorkRec).ExecuteAffrows();
                            break;
                        case 2:
                            msg = "OP90工件出站";
                            cksWorkRec = SaveData(conn, snCodeValue, 127, 1030, ref res);
                            break;
                        case 3:
                            msg = "OP120工件入站";
                            cksWorkRec.PlcID = 130;
                            cksWorkRec.PrimaryCode = snCodeValue;
                            cksWorkRec.CreatedTime = DateTime.Now;
                            cksWorkRec.ReadDB = 1030; //设置读取DB块
                            cksWorkRec.MoveInTime = cksWorkRec.ProductionStartTime = DateTime.Now;
                            res = conn.InsertOrUpdate<CksWorkRecord>().SetSource(cksWorkRec).ExecuteAffrows();
                            break;
                        case 4:
                            msg = "OP120工件出站";
                            cksWorkRec = SaveData(conn, snCodeValue, 130, 1030, ref res);
                            break;
                        default:
                            break;
                    }

                    if (res > 0) {
                        SiemensClient.SetValue(replyRelBindingPos, "1");
                        WriteLogUI($"SN条码：{snCodeValue}，{msg}，保存固化炉进出站记录成功");
                    } else {
                        WriteLogUI($"SN条码：{snCodeValue}，{msg}，保存固化炉进出站记录失败");
                    }

                } else {
                    //复位上位机的信号
                    SiemensClient.SetValue(replyRelBindingPos, "0");
                }

            }
        }

        private CksWorkRecord SaveData(DbConnection conn, string snCodeValue,int plcId,int readDB, ref int res) {
            var sql = conn.Select<CksWorkRecord>().Where(o => o.PlcID == plcId && o.ReadDB == readDB && o.PrimaryCode == snCodeValue).ToSql();
            //获取工件记录
            CksWorkRecord cksWorkRec = conn.Select<CksWorkRecord>().Where(o => o.PlcID == plcId && o.ReadDB == readDB && o.PrimaryCode == snCodeValue).ToList().LastOrDefault();
            if (cksWorkRec == null) {
                res = 0;
                WriteLogUI($"SN条码：{snCodeValue}，保存加工信息失败，未查询到进站记录");
                return null;
            }

            cksWorkRec.ProductionEndTime = cksWorkRec.MoveOutTime = DateTime.Now;
            res = conn.Update<CksWorkRecord>().SetSource(cksWorkRec).ExecuteAffrows();

            //计算工件在工序的加工时长，单位秒
            int? duration = (int?)(cksWorkRec.ProductionEndTime - cksWorkRec.ProductionStartTime)?.TotalSeconds;

            //保存OP90追溯数据
            var act = conn.Select<CksPlcActions>()
                           .Where(a => a.ActionType == 1
                                   && a.PlcId == plcId
                                   && a.ReadDB == readDB
                                   && a.ActionId == DecodeValue.Position.ActionId
                                   && a.ActionKey == DecodeValue.Position.ActionKey)
                           .First();
            var table = conn.Select<CksVirtualTable>().Where(a => a.Id == act.BusinessId).First();
            var columns = conn.Select<CksVirtualColumn>().Where(a => a.TableId == act.BusinessId).OrderBy(a => a.Sequence).ToList();

            string batchNo = $"{Guid.NewGuid().ToString("N")}"; // 批次
            table.MaxSeqId = GetNextSeq(table, conn);//获取当前表格的最大虚拟Id
            CksCollected cl = new CksCollected() {
                BatchCode = batchNo,
                BatchSuffix = GetSuffix(batchNo, 5),
                CreatedTime = DateTime.Now,
                PlcId = plcId,
                ReadDB = readDB,
                SequenceId = table.MaxSeqId,
                TableId = table.Id,
                Nullity = false,
                CycleTime = duration,
                PrimaryCode = snCodeValue,
                Result = 1,
                Suffix_4 = GetSuffix(snCodeValue),
                WorkRecId = cksWorkRec.Id,
                IsDeleted = false,
            };

            List<CksCollectedDetails> details = new List<CksCollectedDetails>();

            //创建实体表字典列数据
            var dicColData = new Dictionary<string, object>();
            dicColData.Add("PlcId", act.PlcId);
            dicColData.Add("BlockDb", act.ReadDB);
            dicColData.Add("CollectBatchCode", batchNo);

            for (int i = 0; i < columns.Count; i++) {
                string content = string.Empty;
                if (columns[i].IsPrimary) {
                    content = snCodeValue;
                }

                if (columns[i].IsCycleTime) {
                    content = duration.Value.ToString();
                }

                if (columns[i].IsResult) {
                    content = "1";
                }

                //峰值炉温
                if (columns[i].ColumnName.ToLower() == "PeekTemp".ToLower()) {
                    var data = DecodeValue.GetLinkDecodeObject(columns[i].DataId);
                    content = data.Value.ToString();
                }

                //谷值炉温
                if (columns[i].ColumnName.ToLower() == "ValleyTemp".ToLower()) {
                    var data = DecodeValue.GetLinkDecodeObject(columns[i].DataId);
                    content = data.Value.ToString();
                }

                //平均炉温
                if (columns[i].ColumnName.ToLower() == "AverageTemp".ToLower()) {
                    var data = DecodeValue.GetLinkDecodeObject(columns[i].DataId);
                    content = data.Value.ToString();
                }

                //烘烤时长
                if (columns[i].ColumnName.ToLower() == "Duration".ToLower()) {
                    content = duration.ToString();
                }

                var model = new CksCollectedDetails() {
                    Content = content,
                    ColumnName = columns[i].ColumnName,
                    ColumnId = columns[i].Id,
                    PlcId = cl.PlcId,
                    TableId = table.Id,
                    BatchSuffix = GetSuffix(batchNo, 5),
                    BatchCode = batchNo,
                    CreatedTime = cl.CreatedTime,
                };
                details.Add(model);
                dicColData.Add(columns[i].ColumnName, content);
            }

            conn.Insert(details).ExecuteAffrows();
            conn.Insert(cl).ExecuteAffrows();
            conn.Update<CksVirtualTable>().SetSource(table)
                .UpdateColumns(a => a.MaxSeqId).ExecuteAffrows();
            base.FreeSql.InsertDict(dicColData).AsTable(table.TableName).ExecuteAffrows();//新增实体表数据

            return cksWorkRec;
        }
    }

}
